import { useMemoizedFn, useUnmount } from 'ahooks';
import { useRef } from 'react';

export interface UseRafFnOptions {
  /**
   * 同时触发多次调用时保留最新的调用
   */
  singleCall?: boolean;
}

/**
 * 创建只会在浏览器下一次重绘之前执行的函数
 *
 * 此功能依赖 [requestAnimationFrame](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame) 而得以实现
 *
 * @param callback 回调函数
 * @param options 配置选项
 */
export function useRafFn<F extends (...args: unknown[]) => unknown>(
  callback: F,
  options: UseRafFnOptions = {}
): (...args: Parameters<F>) => void {
  const { singleCall = true } = options;

  const rafId = useRef<number>();

  function clean() {
    if (rafId.current !== undefined) {
      window.cancelAnimationFrame(rafId.current);
      rafId.current = undefined;
    }
  }

  useUnmount(clean);

  return useMemoizedFn((...args: unknown[]) => {
    if (singleCall) clean();

    rafId.current = window.requestAnimationFrame(() => {
      rafId.current = undefined;
      return callback(...args);
    });
  });
}
